package com.qianyu.project.core.aspect;

import cn.hutool.core.date.DateUtil;
import com.qianyu.project.core.annotation.FlowBegin;
import com.qianyu.project.core.bean.*;
import com.qianyu.project.core.context.handler.FlowHandlerManager;
import com.qianyu.project.core.exception.ModuleIdentityNotFoundException;
import com.qianyu.project.core.exception.FlowNotFoundException;
import com.qianyu.project.core.exception.NotImplementedException;
import com.qianyu.project.core.exception.PrimaryKeyNotFoundException;
import com.qianyu.project.core.service.IFlowNodeService;
import com.qianyu.project.core.service.IFlowService;
import com.qianyu.project.core.service.IFormAuditService;
import com.qianyu.project.core.service.IFormService;
import com.qianyu.project.core.utils.*;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import java.lang.reflect.Method;


/**
 * @author gs
 * @date create in 2020/12/11 15:55
 */
@Aspect
@Component
public class FlowAspect {

    @Autowired
    private IFlowService flowService;
    @Autowired
    private IFlowNodeService flowNodeService;
    @Autowired
    private IFormService formService;
    @Autowired
    private IFormAuditService formAuditService;

    private final Logger logger = LoggerFactory.getLogger(FlowAspect.class);

    @Transactional(rollbackFor = Exception.class)
    @Around("@annotation(flowBegin)")
    public Object around(ProceedingJoinPoint joinPoint, FlowBegin flowBegin) throws Throwable {
        //拿到开启流程需要的参数
        String tableName = flowBegin.value();
        Object moduleId = null;
        //拿到方法返回值
        moduleId = joinPoint.proceed();
        logger.info("拿到模块编号为"+moduleId);
        //判断流程号是否为空
        Assert.moduleIdentityNotNull(moduleId);
        //通过模块拿到第一个流程
        Flow flow = flowService.getByModule(Integer.valueOf(moduleId.toString()));
        logger.info("拿到流程为："+flow.getFlowName());
        //验证是否还存在该流程
        Assert.flowNotNull(flow);
        //通过流程号拿到第一个节点
        FlowNode flowNode = flowNodeService.renderFirtstNode(flow.getFlowId());
        logger.info("流程第一个节点为："+flowNode.getFlowNodeName());
        //调用方法拿到主键
        Object primaryKey = analysisFlowEntry(joinPoint);
        logger.info("目标主键为："+primaryKey);
        //保存申请单
        Form form = saveForm(flow, flowNode, primaryKey.toString(), tableName);
        logger.info("保存审批申请单");
        if(flowNode.getFlowNodeRole() == 0){
            //添加第一层审批节点
            saveFormAudit(form, flowNode);
        }
        logger.info("默认提交第一层节点");

        return moduleId;
    }

    /**
     * description: 获取主键值 <br/>
     * author: gs   <br/>
     * date: 2020/12/18 <br/>
     * params: [joinPoint] <br/>
     * return: java.lang.Object
     */
    private Object analysisFlowEntry(ProceedingJoinPoint joinPoint) throws PrimaryKeyNotFoundException {
        //判断是否返回了result（没有返回就从FlowEntry中尝试获取）
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        Object primaryKey = FlowEntryHandler.parseFlowEntry(method, joinPoint.getArgs());
        //判断
        Assert.primaryKeyNotNull(primaryKey);
        return primaryKey;
    }

    /**
     * description: 保存审批详情 <br/>
     * author: gs   <br/>
     * date: 2020/12/18 <br/>
     * params: [form, eid, flowNode] <br/>
     * return: void
     */
    private void saveFormAudit(Form form,FlowNode flowNode) {
        FormAudit formAudit = new FormAudit();
        formAudit.setFid(form.getFid());
        formAudit.setFlowNodeId(flowNode.getFlowNodeId());
        formAudit.setRemark("提交申请单");
        formAudit.setInfo(FlowResultProvider.AUDIT_ALLOW_SIGN);
        formAudit.setCreatedate(DateUtil.now());
        //执行添加
        formAuditService.save(formAudit);
    }

    /**
     * description: 保存审批单 <br/>
     * author: gs   <br/>
     * date: 2020/12/18 <br/>
     * params: [flow, eid, flowNode, primaryKeyValue, flowType] <br/>
     * return: com.qianyu.flow.core.bean.Form
     */
    private Form saveForm(Flow flow, FlowNode flowNode,
                          String primaryKeyValue, String tableName) {
        Form form = new Form();
        form.setCreatedate(DateUtil.now());
        form.setFlowId(flow.getFlowId());
        form.setCurrent(flowNodeService.renderNextNode(flowNode).getFlowNodeId());
        form.setStatus(FlowResultProvider.FLOW_HANDLE_SIGN);
        form.setId(primaryKeyValue);
        form.setTarget(tableName);
        //执行添加拿到主键
        formService.save(form);
        //返回
        return form;
    }
}
